<template>
  <view
    @click="onClick"
    ref="itemWall"
    class="tm-waterfall-item itemWall"
    :style="[
      !isPush ? { transform: 'translateX(-1000px)' } : '',
      isPush ? { transform: `translateX(${_nodeInfo.left}px) translateY(${_nodeInfo.top}px)` } : '',
    ]"
  >
    <view
      class="container"
      :style="{ borderRadius: props.round + 'px', width: _width + 'px' }"
      :eventPenetrationEnabled="true"
    >
      <view class="item-slot">
        <slot></slot>
      </view>
    </view>
  </view>
</template>

<script lang="ts" setup>
  /**
   * 瀑布流项目
   * @description 不可单独使用，只可放置在tm-waterfall中。
   * @slot default 默认插槽，可以放置任意内容，但不允许异步更改高度，否则瀑布失效。
   * @method img-click 封面图被点击时触发。如果不提供封面图本事件不触发。
   */
  import {
    inject,
    computed,
    type Ref,
    ref,
    getCurrentInstance,
    type ComputedRef,
    toRaw,
    onMounted,
    nextTick,
  } from 'vue';
  import type { itemParenSG } from '../tm-waterfall/interface';

  function getUid(length = 3) {
    return Number(Number(Math.random().toString().substr(3, length) + Date.now()).toString(8));
  }

  // #ifdef APP-PLUS-NVUE
  const dom = uni.requireNativePlugin('dom');
  // #endif
  const proxy = getCurrentInstance()?.proxy ?? null;
  const emits = defineEmits(['img-click', 'click']);
  const props = defineProps({
    round: {
      type: Number,
      default: 4,
    },
  });
  const _width: ComputedRef<number> = inject(
    'tmWaterFallItemRealWidth',
    computed(() => uni.upx2px(_width.value)),
  );

  let _nodeInfo: Ref<itemParenSG> = ref({
    id: getUid(2), //子组件id，唯一。
    width: _width.value,
    height: _width.value,
    imgWidth: _width.value,
    imgHeight: _width.value,
    bottom: 0,
    index: NaN,
    top: 0,
    left: 0,
  });

  const isimgLoad = ref(true);
  const _parentComs = getParent();
  const isPush = ref(false); //是否已经推到父。
  if (!_parentComs) {
    console.error('请不要单独使用此组件，请放置在:tm-waterfall内；');
  }
  _parentComs?.sumTotal(_nodeInfo.value.id);

  onMounted(() => {
    nextTick(() => {
      if (isimgLoad.value === true) {
        //没有异步内容时，直接就是加载渲染完成。
        nvuegetClientRect();
      }
    });
  });

  function getParent() {
    //父级方法。
    let parent = proxy?.$parent;

    while (parent) {
      if (parent?.parentNameId == 'tmWaterfallId' || !parent) {
        break;
      } else {
        parent = parent?.$parent ?? undefined;
      }
    }
    return parent;
  }

  function nvuegetClientRect() {
    nextTick(function () {
      // #ifdef APP-PLUS-NVUE
      dom.getComponentRect(proxy.$refs.itemWall, function (res) {
        if (res?.size) {
          if (res.size.height == 0 && res.size.width == 0) {
            nvuegetClientRect();
          } else {
            isimgLoad.value = true;
            const { width, height } = res.size;
            _nodeInfo.value = {
              ..._nodeInfo.value,
              height: height,
            };
            if (isPush.value === false && isimgLoad.value) {
              pushKey();
              isPush.value = true;
            }
          }
        }
      });
      // #endif
      // #ifndef APP-PLUS-NVUE
      uni
        .createSelectorQuery()
        .in(proxy)
        .select('.itemWall')
        .boundingClientRect((res) => {
          if (res.height === 0 && res.width === 0) {
            nvuegetClientRect();
          } else {
            isimgLoad.value = true;
            const { width, height } = res;
            _nodeInfo.value = {
              ..._nodeInfo.value,
              height: height,
            };
            if (isPush.value === false && isimgLoad.value) {
              pushKey();
              isPush.value = true;
            }
          }
        })
        .exec();
      // #endif
    });
  }

  async function pushKey() {
    if (_parentComs) {
      let pos = await _parentComs.pushKey(toRaw(_nodeInfo.value));
      _nodeInfo.value = pos;
    }
  }

  /** 整个项目被点击。 */
  function onClick(e: TouchEvent) {
    emits('click', _nodeInfo.value);
  }
</script>
<style lang="scss" scoped>
  .tm-waterfall-item {
    position: absolute;
    .container {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      align-content: center;
      justify-content: flex-start;
    }

    .item-slot {
      display: flex;
      flex-direction: column;
      flex: 1;
      align-items: flex-start;
      align-content: center;
      justify-content: flex-start;
    }
  }
</style>
